using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Xml;
using System.Xml.Schema;
using System.Resources;
using Fuzzware.Common;
using Fuzzware.Common.DataSchema;
using Fuzzware.Common.XML;

namespace Fuzzware.Convert2XML.C2X
{
    public class Convert2XML
    {
        XmlSchemaSet oSchemaSet;
        ObjectDataBase oElementDB;
        Encoding OutputEncoding;

        public event C2XProgressEventHandler ProgressEventHandler;

        public Convert2XML(XmlSchemaSet oSchemaSet, ObjectDataBase ElementDB, Encoding OutputEncoding)
        {
            this.oSchemaSet = oSchemaSet;
            this.oElementDB = ElementDB;
            this.OutputEncoding = OutputEncoding;
        }

        public bool Convert(Fuzzware.Schemas.AutoGenerated.Convert2XML C2XInput)
        {
            try
            {
                //System.Diagnostics.Debug.Listeners.Add(new System.Diagnostics.TextWriterTraceListener(Console.Out));
                //System.Diagnostics.Debug.AutoFlush = true;

                // Get the root node name
                XmlQualifiedName RootNodeName = new XmlQualifiedName(C2XInput.RootNodeName, C2XInput.RootNodeNamespace);
                
                // Read in the input file
                byte[] InputFile = null;
                using (FileStream fs = new FileStream(C2XInput.SourceFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                {
                    BinaryReader br = new BinaryReader(fs);
                    InputFile = br.ReadBytes((int)fs.Length);
                }

                XmlDocument oXMLDoc = null;

                // Try to convert the input file to XML
                C2XEngine Engine = new C2XEngine(oSchemaSet, OutputEncoding, oElementDB, ProgressEventHandler);
                ObjectDBEntry[] ObjectDBEntries = oElementDB[RootNodeName];
                if (ObjectDBEntries.Length == 0)
                    Log.Write(MethodBase.GetCurrentMethod(), "Could not find root node name '" + RootNodeName.ToString() + "'", Log.LogType.Error);
                if (ObjectDBEntries.Length > 1)
                    Log.Write(MethodBase.GetCurrentMethod(), "The specified root node name '" + RootNodeName.ToString() + "' is not unique, it must be unique", Log.LogType.Error);
                if (!Engine.Run(InputFile, ObjectDBEntries[0] as ElementDBEntry, C2XInput.OutputNamespacePrefix, out oXMLDoc))
                {
                    Log.Write(MethodBase.GetCurrentMethod(), "Failed to convert '" + C2XInput.SourceFile + "' to XML", Log.LogType.Status);
                    return false;
                }

                string OutputDir = Path.GetDirectoryName(Path.GetFullPath(C2XInput.OutputXMLFile));
                if(!String.IsNullOrEmpty(OutputDir) && !Directory.Exists(OutputDir))
                    Directory.CreateDirectory(OutputDir);

                XmlWriterSettings oWriterSettings = new XmlWriterSettings();
                oWriterSettings.Indent = true;
                oWriterSettings.NewLineHandling = NewLineHandling.None;
                // Write out the XML
                XmlWriter writer = XmlWriter.Create(C2XInput.OutputXMLFile, oWriterSettings);
                oXMLDoc.WriteContentTo(writer);
                writer.Close();

                return true;
            }
            catch (Exception e)
            {
                if (e is System.Threading.ThreadAbortException)
                    throw;
                
                Log.Write(e);
                return false;
            }
        }
    }
}
